package com.abo.yaas.authentication;

import java.util.ArrayList;
import java.util.List;

import com.abo.yaas.domain.User;
import com.vaadin.Application;
import com.vaadin.service.ApplicationContext.TransactionListener;

@SuppressWarnings("serial")
public class SessionHandler implements TransactionListener {
    public static User getUser() {
        return instance.get().user;
    }

    public static void initialize(Application application) {
        if (application == null) {
            throw new IllegalArgumentException("Application may not be null");
        }
        final SessionHandler handler = new SessionHandler(application);
        application.getContext().addTransactionListener(handler);
    }

    public static void removeListener(final UserChangeListener listener) {
        if (instance.get().listeners != null) {
            instance.get().listeners.remove(listener);
        }
    }

    public static void setUser(User user) {
        instance.get().user = user;
        if (user != null) {
            instance.get().fireUserLoggedIn();
        } else {
            instance.get().fireUserLoggedOut();
        }
    }

    private final Application application;

    private User user;

    private List<UserChangeListener> listeners = null;

    private static ThreadLocal<SessionHandler> instance = new ThreadLocal<SessionHandler>();

    public static void addListener(final UserChangeListener listener) {
        if (instance.get().listeners == null) {
            instance.get().listeners = new ArrayList<UserChangeListener>();
        }
        instance.get().listeners.add(listener);
    }

    public SessionHandler(Application application) {
        this.application = application;
        instance.set(this);
    }

    private void fireUserLoggedIn() {
        if (listeners == null) {
            return;
        }
        for (final UserChangeListener listener : listeners) {
            listener.onLogin(new UserChangeEvent(user));
        }
    }

    private void fireUserLoggedOut() {
        if (listeners == null) {
            return;
        }
        for (final UserChangeListener listener : listeners) {
            listener.onLogout(new UserChangeEvent(user));
        }
    }

    @Override
    public void transactionEnd(Application application, Object transactionData) {
        if (this.application == application) {
            instance.set(null);
        }
    }

    @Override
    public void transactionStart(Application application, Object transactionData) {
        if (this.application == application) {
            instance.set(this);
        }
    }

}
